﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Practices.Unity;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Rhino.Mocks;
using TestByWire.AttributeHandlers;

namespace TestByWire.Test.AttributeHandlers.UseStub
{
    [TestClass]
    public class UseStubAttributeTest
    {
    	private IContainerInteraction _target;
    	private IBuildContext _buildContext;

    	[TestMethod]
        public void Inheritance()
    	{
    		_target = new UseStubAttribute(typeof(IMyClass), typeof(MyClass));
    		Assert.IsInstanceOfType(_target, typeof(IContainerInteraction));
    	}

    	[TestMethod]
        public void InteractionOnAnnonymousConstructor()
        {
            IContainerInteraction target = new UseStubAttribute(typeof (IMyClass), typeof (MyClass));
            Assert.AreEqual(typeof(IMyClass), target.RegistrationType);
            Assert.IsNull(target.RegistrationName);
        }

        [TestMethod]
        public void InteractionOnNamedConstructor()
        {
            IContainerInteraction target = new UseStubAttribute(typeof(IMyClass), typeof(MyClass), "name");
            Assert.AreEqual(typeof(IMyClass), target.RegistrationType);
            Assert.AreEqual("name", target.RegistrationName);
        }

    	[TestMethod]
    	public void Execute_ShouldRegisterTypeInContainer()
    	{
			_target = new UseStubAttribute(typeof(IMyClass), typeof(MyClass), "name");
    		ContainerStub.LastRegistration = null;
    		_buildContext = MockRepository.GenerateStub<IBuildContext>();
    		_buildContext.Stub(x => x.Container).Return(new ContainerStub());

    		_target.Execute(_buildContext);

			Assert.AreEqual(typeof(IMyClass), ContainerStub.LastRegistration.Item1);
			Assert.AreEqual(typeof(MyClass), ContainerStub.LastRegistration.Item2);
			Assert.AreEqual("name", ContainerStub.LastRegistration.Item3);
    	}

		[TestMethod]
		public void Execute_ShouldRegisterTypeAsNotToBeStubbed()
		{
			_target = new UseStubAttribute(typeof(IMyClass), typeof(MyClass), "name");
			ContainerStub.PipeLine.DoNotStubList.Clear();
			_buildContext = MockRepository.GenerateStub<IBuildContext>();
			_buildContext.Stub(x => x.Container).Return(new ContainerStub());

			_target.Execute(_buildContext);

			Assert.AreEqual(1, ContainerStub.PipeLine.DoNotStubList.Count);
			DoNotStub notStub = ContainerStub.PipeLine.DoNotStubList[0];
			Assert.AreEqual(new DoNotStub(typeof(IMyClass), "name"), notStub);
		}

    }

	public class ContainerStub : IUnityContainer
	{
		public static Tuple<Type, Type, String> LastRegistration;
		internal static PipelineSettings PipeLine = new PipelineSettings();

		public void Dispose()
		{
			throw new NotImplementedException();
		}

		public IUnityContainer RegisterType(Type from, Type to, string name, LifetimeManager lifetimeManager, params InjectionMember[] injectionMembers)
		{
			LastRegistration=new Tuple<Type, Type, string>(from, to, name);
			return this;
		}

		public IUnityContainer RegisterInstance(Type t, string name, object instance, LifetimeManager lifetime)
		{
			throw new NotImplementedException();
		}

		public object Resolve(Type t, string name, params ResolverOverride[] resolverOverrides)
		{
			if(t == typeof(PipelineSettings))
			{
				return PipeLine;
			}
			return null;
		}

		public IEnumerable<object> ResolveAll(Type t, params ResolverOverride[] resolverOverrides)
		{
			throw new NotImplementedException();
		}

		public object BuildUp(Type t, object existing, string name, params ResolverOverride[] resolverOverrides)
		{
			throw new NotImplementedException();
		}

		public void Teardown(object o)
		{
			throw new NotImplementedException();
		}

		public IUnityContainer AddExtension(UnityContainerExtension extension)
		{
			throw new NotImplementedException();
		}

		public object Configure(Type configurationInterface)
		{
			throw new NotImplementedException();
		}

		public IUnityContainer RemoveAllExtensions()
		{
			throw new NotImplementedException();
		}

		public IUnityContainer CreateChildContainer()
		{
			throw new NotImplementedException();
		}

		public IUnityContainer Parent
		{
			get { throw new NotImplementedException(); }
		}

		public IEnumerable<ContainerRegistration> Registrations
		{
			get { throw new NotImplementedException(); }
		}
	}
}
